package com.mofei.h003test.presenter;

import android.util.Log;

import com.jakewharton.rx.ReplayingShare;
import com.mofei.h003test.H003TestApplication;
import com.mofei.h003test.HexString;
import com.mofei.h003test.activity.ControlActivity;
import com.polidea.rxandroidble2.RxBleConnection;
import com.polidea.rxandroidble2.RxBleDevice;
import com.polidea.rxandroidble2.RxBleDeviceServices;
import com.trello.rxlifecycle2.LifecycleTransformer;
import com.trello.rxlifecycle2.android.ActivityEvent;

import java.util.UUID;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.SingleSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.subjects.PublishSubject;

/**
 * @author : timmy
 * @date : 2018/9/20
 */
public class ControlActivityPresenter {

    private Observable<RxBleConnection> mConnectionObservable;
    private ControlActivity mControlActivity;
    private RxBleDevice mBleDevice;
    private PublishSubject<Boolean> mDisconnectTriggerSubject = PublishSubject.create();
    private Disposable mConnectDispisable;

    private static final UUID mCharacteristicUuid = UUID.fromString(H003TestApplication.CharacteristicUuid);
    private static final UUID mCharacteristicUuid_NOTI = UUID.fromString(H003TestApplication.CHARACTERISTICUUID_NOTIFY);
    private static final UUID mCharacteristicUuid_write = UUID.fromString(H003TestApplication.CHARACTERISTICUUID_WRITE);

    public ControlActivityPresenter(ControlActivity activity, String macAddress) {
        mControlActivity = activity;
        mBleDevice = H003TestApplication.getRxBleClient(activity).getBleDevice(macAddress);
        monitoringDeviceConnectStart();
        mConnectionObservable = prepareConnectionObservable();
    }

    private Observable<RxBleConnection> prepareConnectionObservable() {
        LifecycleTransformer<RxBleConnection> lifecycleTransformer = mControlActivity.bindUntilEvent(ActivityEvent.PAUSE);
        ReplayingShare<RxBleConnection> replayingShare = ReplayingShare.instance();
        return mBleDevice
                .establishConnection(false)
                .takeUntil(mDisconnectTriggerSubject)
                .compose(lifecycleTransformer)
                .compose(replayingShare);
    }

    public boolean isConnected() {
        return mBleDevice.getConnectionState() == RxBleConnection.RxBleConnectionState.CONNECTED;
    }

    /**
     * 监听设备的连接情况
     */
    private void monitoringDeviceConnectStart() {
        // 负责监听设备的连接情况

        if (mConnectDispisable != null) {
            mConnectDispisable.dispose();
            mConnectDispisable = null;
        } else {
            LifecycleTransformer<RxBleConnection.RxBleConnectionState> lifecycleTransformer =
                    mControlActivity.bindUntilEvent(ActivityEvent.DESTROY);
            // onConnectionStateChange(rxBleConnectionState);
            mConnectDispisable = mBleDevice.observeConnectionStateChanges()
                    .compose(lifecycleTransformer)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<RxBleConnection.RxBleConnectionState>() {
                        @Override
                        public void accept(RxBleConnection.RxBleConnectionState rxBleConnectionState) throws Exception {
                            if (rxBleConnectionState == RxBleConnection.RxBleConnectionState.CONNECTING) {
                                // 设备连接中
                                mControlActivity.connectState(1);
                            } else if (rxBleConnectionState == RxBleConnection.RxBleConnectionState.CONNECTED) {
                                // 设备连接成功
                                mControlActivity.connectState(2);
                            } else if (rxBleConnectionState == RxBleConnection.RxBleConnectionState.DISCONNECTING) {
                                // 设备断连中
                            } else if (rxBleConnectionState == RxBleConnection.RxBleConnectionState.DISCONNECTED) {
                                // 设备已经断开连接
                                mControlActivity.connectState(3);
                            }
                        }
                    });
        }
    }

    public void startConnectDevice() {
        // 开始连接设备
        Disposable subscribe = mConnectionObservable
                .flatMapSingle(new Function<RxBleConnection, SingleSource<? extends RxBleDeviceServices>>() {
                    @Override
                    public SingleSource<? extends RxBleDeviceServices> apply(RxBleConnection rxBleConnection) throws Exception {
                        return rxBleConnection.discoverServices();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .doFinally(new Action() {
                    @Override
                    public void run() throws Exception {
                        // 我也不知道这是啥 断开连接的时候会调用
                    }
                })
                .subscribe(new Consumer<RxBleDeviceServices>() {
                    @Override
                    public void accept(RxBleDeviceServices rxBleDeviceServices) throws Exception {
                        // 服务发现成功, 前去打开服务
                        registerNotify();
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        throwable.printStackTrace();
                        mControlActivity.showToast("服务发现失败");
                    }
                });
    }

    public void triggerDisconnect() {
        mDisconnectTriggerSubject.onNext(true);
    }


    public void registerNotify() {
        Disposable subscribe = mConnectionObservable
                .flatMap(new Function<RxBleConnection, ObservableSource<Observable<byte[]>>>() {
                    @Override
                    public ObservableSource<Observable<byte[]>> apply(RxBleConnection rxBleConnection) throws Exception {
                        return rxBleConnection.setupNotification(mCharacteristicUuid_NOTI);
                    }
                })
                .doOnNext(new Consumer<Observable<byte[]>>() {
                    @Override
                    public void accept(Observable<byte[]> observable) throws Exception {
                        mControlActivity.showToast("通知已经打开");
                    }
                })
                .flatMap(new Function<Observable<byte[]>, ObservableSource<byte[]>>() {
                    @Override
                    public ObservableSource<byte[]> apply(Observable<byte[]> observable) throws Exception {
                        return observable;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<byte[]>() {
                    @Override
                    public void accept(byte[] bytes) throws Exception {
                        // 通过通知获取到的数据

                        String data = HexString.bytesToHex(bytes);
                        // mControlActivity.showToast("收到的通知消息+" + data);
                        Log.i("gzw", "收到的通知消息: " + data);

                        byte aByte = bytes[0];

                        if (aByte == (byte) 0xC0) {
                            // 确定有从机地址
                            mControlActivity.setSalveAddress(data);
                        }

                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                    }
                });
    }

    public void registerWrite(byte[] data) {
        boolean isConnected = isConnected();
        if (isConnected) {
            writeData(data);
        } else {
            mControlActivity.showToast("蓝牙未连接");
        }
    }

    private void writeData(final byte[] data) {
        Disposable subscribe = mConnectionObservable.firstOrError()
                .flatMap(new Function<RxBleConnection, SingleSource<byte[]>>() {
                    @Override
                    public SingleSource<byte[]> apply(RxBleConnection rxBleConnection) throws Exception {

                        String datastr = HexString.bytesToHex(data);
                        //mControlActivity.showToast("发送的消息+" + data);
                        //Log.i("gzw", "收到的通知消息: " + datastr);

                        byte[] unbind = {(byte) 0xBB, (byte) 0x8D, (byte) 0x0B, (byte) 0x00, (byte) 0x00, (byte) 0x82};

                        // 发送命令的地方
                        return rxBleConnection.writeCharacteristic(mCharacteristicUuid_write, data);
                    }
                }).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<byte[]>() {
                    @Override
                    public void accept(byte[] bytes) throws Exception {
                        //  mControlActivity.showToast("写入成功");

                        byte index0 = bytes[0];
                        byte index1 = bytes[1];
                        byte index2 = bytes[2];

                        if (index0 == (byte) 0xBB && index1 == (byte) 0x8D && index2 == (byte) 0x0B) {
                            mControlActivity.showToast("解绑成功");
                        }

                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        // mControlActivity.showToast("写入失败");
                    }
                });
    }
}
